

#include <linux/err.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/device.h>

#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>

#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
#include <linux/mtd/spi-nor.h>

#include <linux/delay.h>

#include <linux/of.h>
#include <linux/of_gpio.h>

#include <linux/types.h>
#include <linux/printk.h>
#include <linux/bug.h>
#include <linux/kernel.h>


#include <linux/interrupt.h>

/*三个字符设备函数*/
#include <linux/fs.h>

/*MKDEV转换设备号数据类型的宏定义*/
#include <linux/kdev_t.h>

/*定义字符设备的结构体*/
#include <linux/cdev.h>

/*包含函数device_create 结构体class等头文件*/
#include <linux/device.h>

#include <linux/sched.h>
#include <linux/wait.h>

#include <linux/irq.h>
#include <linux/interrupt.h>


#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>

/*copy from user*/
#include <asm/uaccess.h>


#include "nrf.h"
#include "nrf_ioctrl.h"




#define u8 unsigned char

#define  DEV_NMAE "nrf2410"

#define CONNECTED 1
#define DISCONNECTED 0

#define NRF_SEND_O 0
#define NRF_READ_O 1
#define NRF_FREE_O 2


struct nrf_2410_t{


	dev_t dev_num;
	char * dev_name;
    struct class *myclass; 
	struct device *my_device;
	struct cdev  cdev;
	
	struct timer_list irqtimer;
	
	u8 *rx_cache;
	
	wait_queue_head_t nrf_send_wait;
	wait_queue_head_t nrf_receive_wait;

	struct fasync_struct *async_queue;
	
	u8 condition;
	u8 nrf_status;		//
	u8 operate_status;
	u8 async_status;

	
	
};	


struct nrf_2410_t  nrf_2410;


/*the io number*/
int nrf_ce = 0;

int nrf_cs = 0;

int nrf_irq_gpio = 0;

int nrf_irq = 0;	

enum ASYNC_STATUS{

	ASYNC_FREE = 0,
	ASYNC_W8R8,	

};



#define SET 	1
#define RESET 	0

/*spi片选*/
#define NRF_CSN(x)    do{ gpio_set_value(nrf_cs, x); }while(0)

/*CE 低进入待机模式*/
#define NRF_CE(x)	  do{ gpio_set_value(nrf_ce, x); }while(0)	
	     
#define NRF_Read_IRQ()		;

struct spi_device *nrf_spi = NULL;

int TX_PLOAD_WIDTH = 32;
int RX_PLOAD_WIDTH = 32;
int CHANAL = 0;

/*用于异步传输*/
struct spi_message spi_msg_all;
struct spi_transfer transfer_all[2] = {};
u16 r_data_all = 0;
u16 w_data_all = 0;



//u8 *RX_BUF;	   //接收数据缓存
//u8 *TX_BUF;	   //发射数据缓存
u8 TX_ADDRESS[TX_ADR_WIDTH] = {0xFF,0xFF,0xFF,0xFF,0xFF};  // 定义一个静态发送地址
u8 RX_ADDRESS[RX_ADR_WIDTH] = {0xFF,0xFF,0xFF,0xFF,0xFF};




int nrf_spi_w8r8_async(u8 pBuf)
{

	/*置低CSN，片选*/
	NRF_CSN(RESET);
	
	/*进入待机模式*/
	NRF_CE(RESET);


	struct spi_device *spi = nrf_spi;
	
	w_data_all = pBuf;
	
	transfer_all[0].tx_buf = &w_data_all;
	transfer_all[0].len = 1;
	spi_message_add_tail(&transfer_all[0], &spi_msg_all);

	transfer_all[1].rx_buf = &r_data_all;
	transfer_all[1].len = 1;
	spi_message_add_tail(&transfer_all[1], &spi_msg_all);

	return spi_async(spi, &spi_msg_all);



}



u8 nrf_spi_write8(u8 pBuf)
{
	struct spi_device *spi = nrf_spi;
	struct spi_transfer t[1] = {};
	struct spi_message m;

	u16 t_data = pBuf;

	
	spi_message_init(&m);


	t[0].tx_buf = &t_data;
	t[0].len = 1;
	spi_message_add_tail(&t[0], &m);


	return spi_sync(spi, &m);
}


u8 nrf_spi_read8(void)
{
	struct spi_device *spi = nrf_spi;
	struct spi_transfer t[1] = {};
	struct spi_message m;

	u16 r_data = 0;

	
	spi_message_init(&m);

	t[0].rx_buf = &r_data;

	t[0].len = 1;

	spi_message_add_tail(&t[0], &m);

	spi_sync(spi, &m);


	return r_data;

}


/**
  * @brief   用于向NRF特定的寄存器写入数据
  * @param   
  *		@arg reg:NRF的命令+寄存器地址
  *		@arg dat:将要向寄存器写入的数据
  * @retval  NRF的status寄存器的状态
  */
u8 SPI_NRF_WriteReg(u8 reg,u8 dat)
{
 	u8 status;
	
	 /*置低CSN，片选*/
	 NRF_CSN(RESET);
	 
	 /*进入待机模式*/
	 NRF_CE(RESET);


				
	/*发送命令及寄存器号 */
	status = nrf_spi_write8(reg);
		 
	 /*向寄存器写入数据*/
  	nrf_spi_write8(dat);


	
	/*CSN拉高，完成*/	   
  	 NRF_CSN(SET);

	/*进入工作模式*/
	//NRF_CE(SET);

		
	/*返回状态寄存器的值*/
   	return(status);
}


/**
  * @brief   用于从NRF特定的寄存器读出数据
  * @param   
  *		@arg reg:NRF的命令+寄存器地址
  * @retval  寄存器中的数据
  */
u8 SPI_NRF_ReadReg(u8 reg)
{
 	u8 reg_val;
	u8 status;

	/*置低CSN，片选*/
	NRF_CSN(RESET);

	/*进入待机模式*/
	NRF_CE(RESET);

				
	/*发送命令及寄存器号 */
	status = nrf_spi_write8(reg);
	//printk("write 8 status %d \n", status);

	
	 /*读取寄存器的值 */
 	 reg_val = nrf_spi_read8();
	          
	/*CSN拉高，完成*/	   
  	 NRF_CSN(SET);

	/*进入工作模式*/
	//NRF_CE(SET);
		
	/*返回状态寄存器的值*/
   	return(reg_val);

}



/**
  * @brief   用于向NRF的寄存器中写入一串数据
  * @param   
  *		@arg reg : NRF的命令+寄存器地址
  *		@arg pBuf：存储了将要写入写寄存器数据的数组，外部定义
  * 	@arg bytes: pBuf的数据长度
  * @retval  NRF的status寄存器的状态
  */

u8 SPI_NRF_WriteBuf(u8 reg ,u8 *pBuf,u8 bytes)
{

	u8 status;

	/*置低CSN，片选*/
	NRF_CSN(RESET);

	/*进入待机模式*/
	NRF_CE(RESET);
	
	status = nrf_spi_write8(reg); 

	//printk("write 8 status %d \n", status);
	
	 /*向缓冲区写入数据*/
	spi_write(nrf_spi, pBuf, bytes);
	

	NRF_CSN(SET);

	/*进入工作模式*/
	//NRF_CE(SET);

	return (status);	//返回NRF24L01的状态 		
}


/**
  * @brief   用于向NRF的寄存器中写入一串数据
  * @param   
  *		@arg reg : NRF的命令+寄存器地址
  *		@arg pBuf：用于存储将被读出的寄存器数据的数组，外部定义
  * 	@arg bytes: pBuf的数据长度
  * @retval  NRF的status寄存器的状态
  */
u8 SPI_NRF_ReadBuf(u8 reg,u8 *pBuf,u8 bytes)
{
 	u8 status;

	 /*置低CSN，使能SPI传输*/
	 NRF_CSN(RESET);
	
	/*进入待机模式*/
	NRF_CE(RESET);

	
	/*发送寄存器号*/		
	status = nrf_spi_write8(reg); 
	//printk("write 8 status %d \n", status);

 	/*读取缓冲区数据*/
	 	 
	spi_read(nrf_spi, pBuf, bytes);
 
	 /*CSN拉高，完成*/
	NRF_CSN(SET);	

	/*进入工作模式*/
	//NRF_CE(SET);
		
 	return status;		//返回寄存器状态值
}


void NRF_init(void)
{
	
	SPI_NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH);    //写TX节点地址 
    SPI_NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH); //设置RX节点地址,主要为了使能ACK   
  
   
	SPI_NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01);    		//使能通道0的自动应答    
	SPI_NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01);		//使能通道0的接收地址    

	SPI_NRF_WriteReg(NRF_WRITE_REG+RF_CH,CHANAL);       //设置RF通道为CHANAL
	
	SPI_NRF_WriteReg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度  
    
  	SPI_NRF_WriteReg(NRF_WRITE_REG+RF_SETUP,0x0f); 		//设置TX发射参数,0db增益,2Mbps,低噪声增益开启   
  
   	SPI_NRF_WriteReg(NRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次

    SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG, 0x0f);  		//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式 

}   
	

/**
  * @brief  配置并进入接收模式 PRIM_RX
  * @param  无
  * @retval 无
  */
void NRF_RX_Mode(void)

{
	NRF_CE(RESET);	
	SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG, 0x0f);  		//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式 
	NRF_CE(SET);
}   


/**
  * @brief  配置发送模式 PRIM_RX
  * @param  无
  * @retval 无
  */
void NRF_TX_Mode(void)		
{  
	NRF_CE(RESET);	
	SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG,0x0e);    //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,发射模式,开启所有中断
	NRF_CE(SET);
	
	udelay(15);
   
}



void nrf_spi_complete(void * contex)
{


	u8 status =  r_data_all;
	int i=0;

	printk("nrf_spi_complete %x\n", r_data_all);
	//NRF_CSN(SET);
	
	
	if(nrf_2410.async_status == ASYNC_W8R8 ){

			printk("ck!\n");
			
			if(status & TX_DS){

				nrf_2410.operate_status = NRF_FREE_O;
				nrf_2410.condition = 1; 
				wake_up_interruptible(&nrf_2410.nrf_send_wait);
				printk("wake up!1");
				
			}else if(status & MAX_RT){
				printk(" error MAX_RT\n");
				SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS, status); 
				nrf_2410.operate_status = ERROR;
				
			}else if(status & RX_DR){	//收到数据
				
				kill_fasync(&nrf_2410.async_queue, SIGIO, POLL_OUT);
				
				
				
			}else{

				printk("other error\n");
				SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS, status); 

			}
			
		mod_timer(&nrf_2410.irqtimer,jiffies +1000);
		nrf_2410.async_status = ASYNC_FREE;
		
	}else{


		printk("other!\n");
		
	}
	//u8 status = *(char *)transfer_all[0].rx_buf;

	//mod_timer(&nrf_2410.irqtimer,jiffies +100);  //激活已经完成的timer

	//NRF_CE(SET);
	

}





/**
  * @brief   用于向NRF的发送缓冲区中写入数据
  * @param   
  *		@arg txBuf：存储了将要发送的数据的数组，外部定义	
  * @retval  发送结果，成功返回TXDS,失败返回MAXRT或ERROR
  */
u8 NRF_Tx_Dat(u8 *txbuf)
{
	u8 state;  

	NRF_TX_Mode();

	printk("TX data!\n");
	/*写数据到TX BUF 最大 32个字节*/						
	SPI_NRF_WriteBuf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);

	NRF_CE(SET);

	nrf_2410.operate_status = NRF_SEND_O;
	
	 /*等待发送完成中断    */                         
	state = wait_event_interruptible_timeout(nrf_2410.nrf_send_wait, nrf_2410.condition, 2*HZ);
	if(state == 0)printk("@condition evaluated to false after the @timeout elapsed\n");
	
	nrf_2410.condition = 0;
	printk("wake up! ok");
	
	/*读取状态寄存器的值 */                              
	//state = SPI_NRF_ReadReg(STATUS);
	state = r_data_all;

	 /*清除TX_DS或MAX_RT中断标志*/                  
	SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,state); 	

	SPI_NRF_WriteReg(FLUSH_TX,NOP);    //清除TX FIFO寄存器 

	NRF_RX_Mode();			//切回到接收模式

	nrf_2410.async_status =0;

	 /*判断中断类型*/    
	if(state&MAX_RT){

		printk("MAX rt\n");
		return MAX_RT;//达到最大重发次数
		
	}else if(state&TX_DS){

		printk("send ok DS\n");
		return TX_DS; //发送完成

	}else if(state & RX_DR){	//收到数据
		
		printk("recevie\n");
		SPI_NRF_ReadBuf(RD_RX_PLOAD, nrf_2410.rx_cache, RX_PLOAD_WIDTH);//读取数据
		SPI_NRF_WriteReg(FLUSH_RX,NOP); 		 //清除RX FIFO寄存器
		printk("receive data\n");
			
	}
	
} 


/**
  * @brief   用于从NRF的接收缓冲区中读出数据
  * @param   
  *		@arg rxBuf ：用于接收该数据的数组，外部定义	
  * @retval 
  *		@arg 接收结果
  */
u8 NRF_Rx_Dat(u8 *rxbuf)
{

	
}



/**
  * @brief  主要用于NRF与MCU是否正常连接
  * @param  无
  * @retval SUCCESS/ERROR 连接正常/连接失败
  */
u8 NRF_Check(void)
{
	u8 buf[5] = {0xC1,0xC2,0xC3,0xC4,0xC5};
	u8 buf1[5] = {0};
	u8 i = 0; 
	 
	/*写入5个字节的地址.  */  
	SPI_NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,buf,5);

	/*读出写入的地址 */
	SPI_NRF_ReadBuf(TX_ADDR,buf1,5*sizeof(u8)); 
             
	for(i=0; i<5; i++)
	{

		printk(" %x ",buf1[i]);
		
	} 
	
	 printk(" \n ");
	
	/*check the data*/               
	for(i=0; i<5; i++)
	{
		if(buf1[i] != buf[i])
		break;
		
	} 
	       
	if(i==5){
		
		nrf_2410.nrf_status = CONNECTED;
		
		return 0xff ;        //MCU与NRF成功连接 
		
	}else{

		nrf_2410.nrf_status = DISCONNECTED;
	}

	return i ;        //MCU与NRF不正常连接
}


static irqreturn_t nrf_isr(int irq, void *dev_id)
{
	
	u8 status = 0;

	//printk("#irq\n");

	/*maybe this is send irq*/
	if(nrf_2410.operate_status == NRF_SEND_O){

		//nrf_2410.operate_status = NRF_FREE_O;
		//nrf_2410.condition = 1; 
		//wake_up_interruptible(&nrf_2410.nrf_send_wait);
		
	
		//return IRQ_HANDLED;
	}
	
	/*read the nrf status reg*/     
	nrf_2410.async_status = ASYNC_W8R8;
	status =  nrf_spi_w8r8_async(STATUS);   

	return IRQ_HANDLED;
}

void timer_irq_fun(void)
{

		int val = -1;
		u8 status = 0;

		//printk("timer !\n");
		
		val = gpio_get_value(nrf_irq_gpio);
				
		
		if(val == 0 && nrf_2410.async_status != ASYNC_W8R8){
		
			/*read the nrf status reg*/ 	
			printk("low var!\n");
			
			nrf_2410.async_status = ASYNC_W8R8;
			status =  nrf_spi_w8r8_async(STATUS);	
		
		
		}else{
		
			mod_timer(&nrf_2410.irqtimer,jiffies +100);  //激活已经完成的timer
		
		
		}


}



static int nrf_open (struct inode * node, struct file * filep)
{

	NRF_init();
	NRF_RX_Mode();			//接收模式
	printk(KERN_INFO"#nrf open\n");



	return 0;

}

static ssize_t nrf_read (struct file * file, char __user * buf, size_t size, loff_t * loff)
{
	u8 send_data[32] = {0};
	u8 ret = 0;
	u8 status = r_data_all;
	u8 i=0;

	if(nrf_2410.nrf_status == DISCONNECTED)goto ERROR_status;

	/*check the data length*/
	if(size > TX_PLOAD_WIDTH)goto ERROR_too_long;

	
	/*BUG 必须读2次*/
	SPI_NRF_ReadBuf(RD_RX_PLOAD, nrf_2410.rx_cache, RX_PLOAD_WIDTH*sizeof(u8));//读取数据
	SPI_NRF_ReadBuf(RD_RX_PLOAD, nrf_2410.rx_cache, RX_PLOAD_WIDTH*sizeof(u8));//读取数据
	
	printk("flag 2!\n");
	
	SPI_NRF_WriteReg(FLUSH_RX,NOP);		 //清除RX FIFO寄存器

	printk("flag 1!\n");

	SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS, status); 
	NRF_CE(1);	//继续接收

	nrf_2410.async_status = ASYNC_FREE;
	
	
	printk("flag 3!\n");
	
	for(i=0; i<RX_PLOAD_WIDTH; i++)
			printk("# %x ", nrf_2410.rx_cache[i]);

	printk("\n");
	
	copy_to_user(buf, nrf_2410.rx_cache, size);
	

	return 0;
	
ERROR_too_long:

	printk(KERN_INFO"data too long max 32 byts \n");				
	return -1;
	
ERROR_status:
		
	printk(KERN_INFO"connect nrf error\n");
	return -2;

}


static ssize_t nrf_write (struct file * file, const char __user * buf, size_t size, loff_t * ppos)
{
	u8 send_data[32] = {0};
	u8 ret = 0;

	if(nrf_2410.nrf_status == DISCONNECTED)goto ERROR_status;
	
	/*check the data length*/
	if(size > TX_PLOAD_WIDTH)goto ERROR_too_long;

	//NRF_TX_Mode();
	
	/*用户空间->内核空间*/
	if (copy_from_user(send_data, buf, size)){
		

		 ret =  - EFAULT;
	}
	else{

		 //printk("spi_msg_all.status = %d \n", spi_msg_all.status);
		 
		if (NRF_Tx_Dat(send_data) == ERROR){

			printk(KERN_INFO"# nrf_write FAIL\n");
			return -1;
		}

	}

	
	//printk(KERN_INFO"# nrf_write ok\n");


	return ret;

ERROR_too_long:
	
	printk(KERN_INFO"data too long max 32 byts \n");
		
	return -1;
ERROR_status:
	
	printk(KERN_INFO"connect nrf error\n");
	return -2;

		
}

long nrf_ctl (struct file * file, unsigned int cmd, unsigned long arg)
{

	printk("ioctl %d \n", cmd);

	switch(cmd){

		case NRF_CK:
		{
			while(nrf_2410.async_status == ASYNC_W8R8)
					msleep(1);
		
			if (NRF_Check() == 0xff){

				printk(KERN_INFO"\n found NRF! \n");
				nrf_2410.nrf_status = CONNECTED;
			}
			
			NRF_init();
			
			break;
		}

		case NRF_CNT_STATUS:
		{
			if(arg != 0)
				if(copy_to_user((u8 *)arg, &nrf_2410.nrf_status, sizeof(u8)))
						return -EFAULT;

			break;
		}
		case NRF_RECIVE_DATA:
		{


			break;
		}




	}


	NRF_RX_Mode();
	
}


/* fasync函数*/
static int nrf_fasync(int fd, struct file *filp, int mode)
{
	printk("nrf_fasync init");
	return fasync_helper(fd, filp, mode, &nrf_2410.async_queue);
	 
}

/*文件释放函数*/
int nrf_release(struct inode *inode, struct file *filp)
{

      fasync_helper(-1, filp, 0,  &nrf_2410.async_queue);
 	  return 0;
}



static const struct file_operations file_operat={
	
	.llseek = NULL,
	.owner = THIS_MODULE,
	.unlocked_ioctl= nrf_ctl,
   	.open = nrf_open,
  	.read = nrf_read,
  	.write = nrf_write,
  	 .release = nrf_release,
  	.fasync = nrf_fasync,
	
	
};



static int nrf_probe(struct spi_device *spi)
{
	u8 re = 0;
	
	printk("emmmm\n");

	nrf_2410.async_status = 0;
	nrf_2410.nrf_status = DISCONNECTED;
	nrf_2410.rx_cache = (u8 *)kmalloc(sizeof(u8) * RX_PLOAD_WIDTH *2, GFP_KERNEL);


	spi->bits_per_word = 8;
	spi->mode = SPI_MODE_0;
	spi->max_speed_hz = 500000;

	/*survey nrf*/
	re = spi_setup(spi);
	

	if (re < 0)printk(KERN_INFO"not found spi mode 0 \n");
	

	nrf_spi = spi;

	/*get ce*/
	
	//nrf_ce = of_get_named_gpio(spi->dev.of_node, "ce-gpios", 0);
	nrf_ce = 54;
	printk("nrf_ce gpio_num = %d\n", nrf_ce);
	if (nrf_ce > 0)devm_gpio_request(&spi->dev, nrf_ce, "nrf_ce");
	
	/*get cs*/
	//nrf_cs = of_get_named_gpio(spi->dev.of_node, "cns-gpios", 0);
	nrf_cs = 55;
	printk("nrf_cs gpio_num = %d\n", nrf_cs);
	if (nrf_cs > 0)devm_gpio_request(&spi->dev, nrf_cs, "nrf_ce");

	/*get irq*/
	//nrf_irq_gpio = of_get_named_gpio(spi->dev.of_node, "irq-gpios", 0);
	nrf_irq_gpio = 57;
	printk("nrf_irq gpio_num = %d\n", nrf_irq_gpio);
	if (nrf_irq > 0)devm_gpio_request(&spi->dev, nrf_irq_gpio, "nrf_irq");

	gpio_direction_output(nrf_cs, 1);
	gpio_direction_output(nrf_ce, 1);
	
	gpio_direction_input(nrf_irq_gpio);

	/* test
	msleep(500);
	gpio_set_value(nrf_irq_gpio, 0);
	msleep(500);
	gpio_set_value(nrf_irq_gpio, 1);
	*/
	
	/*set irq gpio and requst irq
	nrf_irq = gpio_to_irq(nrf_irq_gpio);
	if (nrf_irq < 0)dev_err(&spi->dev, "gpio to irq error %d\n", nrf_irq);
	printk("nrf_irq num = %d\n", nrf_irq);

	devm_request_irq(&spi->dev, nrf_irq, nrf_isr,IRQF_TRIGGER_FALLING, "nrf", nrf_spi);
	*/

	/*set the wait event*/
	init_waitqueue_head(&nrf_2410.nrf_send_wait);	

	spi_message_init(&spi_msg_all);
	spi_msg_all.complete = nrf_spi_complete;

	




	
	NRF_CSN(SET);

	if (NRF_Check() == 0xff){
		
		printk(KERN_INFO"\n found NRF! \n");
		
	
	}else{

		if (NRF_Check() == 0xff){
			
			printk(KERN_INFO"\n found NRF! \n");
			
			}else{

				printk(KERN_INFO"\n not found NRF! buf = %d \n", re);

			}


	}


	init_timer(&nrf_2410.irqtimer);
	setup_timer(&nrf_2410.irqtimer,  timer_irq_fun, 0);
	nrf_2410.irqtimer.expires = jiffies + 100;
	add_timer(&nrf_2410.irqtimer);
	

	
	re = alloc_chrdev_region(&nrf_2410.dev_num , 0, 1, DEV_NMAE);

	if(re<0) //动态申请设备号失败
	{
		printk(KERN_INFO "alloc_num error!! \n");
		return -1;
	}else{
		
		printk(KERN_INFO "alloc_num bingo major is %d \n",MAJOR(nrf_2410.dev_num));
	}

	nrf_2410.myclass = class_create(THIS_MODULE,DEV_NMAE);
	

	cdev_init(&nrf_2410.cdev, &file_operat);
	nrf_2410.cdev.owner = THIS_MODULE;
	nrf_2410.cdev.ops = &file_operat;
	re = cdev_add(&nrf_2410.cdev, nrf_2410.dev_num, 1);

	nrf_2410.my_device = device_create(nrf_2410.myclass, NULL, nrf_2410.dev_num, NULL, DEV_NMAE);
	
	
NOT_FOUND:
	

	return 0;
}


static int nrf_remove(struct spi_device *spi)
{

	kfree(nrf_2410.rx_cache);
	
	device_destroy(nrf_2410.my_device, nrf_2410.dev_num);

	class_destroy(nrf_2410.myclass);

	cdev_del(&nrf_2410.cdev);

	unregister_chrdev(MAJOR(nrf_2410.dev_num), DEV_NMAE);
	
	return 0;
}





static struct spi_driver nrf_driver = {
	.driver = {
		.name =		"yin,nrf",
		.owner =	THIS_MODULE,
	},
	.probe =	nrf_probe,
	.remove =	nrf_remove,

	/* NOTE:  suspend/resume methods are not necessary here.
	 * We don't do anything except pass the requests to/from
	 * the underlying controller.  The refrigerator handles
	 * most issues; the controller driver handles the rest.
	 */
};


module_spi_driver(nrf_driver);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("junchao_zhao@yeah.net");
MODULE_DESCRIPTION("SPI driver for NRF2401");
